﻿using System;
using System.Diagnostics.Contracts;
using System.Globalization;
using System.Text;

namespace YaTools.Yaml
{
    public struct ErrorId
    {
        private readonly string _id;

        public ErrorId(string id)
        {
            Contract.Requires(id != null);
            Contract.Requires(id.Length == 5);
            _id = id;
        }

        [ContractInvariantMethod]
        // ReSharper disable UnusedMember.Local
        private void ObjectInvariants()
        // ReSharper restore UnusedMember.Local
        {
            Contract.Invariant(_id != null);
            Contract.Invariant(_id.Length == 5);
        }

        public override string ToString()
        {
            return _id;
        }

        public int ErrorNumber
        {
            get
            {
                try
                {
                    return int.Parse(_id.Substring(2));
                }
                catch (Exception ex)
                {
                    throw new FormatException(String.Format("Invalid error ID '{0}'", _id), ex);
                }
            }
        }

        [Pure]
        public string GetMessage(params object[] args)
        {
            Contract.Requires(args != null);
            string message;
            string format = Errors.ResourceManager.GetString(_id);
            if (format == null) format = _id;
            try
            {
                var sb = new StringBuilder();
                sb.AppendFormat(CultureInfo.InvariantCulture, format, args);
                sb.AppendFormat(CultureInfo.InvariantCulture, "  ({0})", _id);
                message = sb.ToString();
            }
            catch (FormatException ex)
            {
                message = string.Format(CultureInfo.InvariantCulture, "{0} : Error formating message: {1}",
                                        _id, ex.Message);
            }
            return message;
        }

        public static implicit operator ErrorId(string id)
        {
            Contract.Requires(id != null);
            Contract.Requires(id.Length == 5);
            if (!id.StartsWith("YA"))
                throw new ArgumentException("ErrorId must be of the form YA999");
            return new ErrorId(id);
        }
    }
}